package com.macasa.service.dal.impl;

import java.io.Serializable;
import java.util.List;

import org.hibernate.Criteria;
import org.springframework.transaction.annotation.Transactional;

import com.macasa.panel.common.log.Logger;
import com.macasa.panel.common.log.annotations.ILoggable;
import com.macasa.panel.dao.hibernate.api.IDao;
import com.macasa.panel.entity.api.IModel;
import com.macasa.panel.exception.DALException;
import com.macasa.panel.exception.DAOException;
import com.macasa.service.dal.api.ICRUDDal;

/**
 * Class AbstractCRUDSService
 * <P>
 * 
 * @param <ID>
 *            ID
 * @param <ID_TYPE>
 *            ID Type
 * @author Mickaël Husson
 * @date 01/01/2012
 */
public abstract class AbstractCRUDDal<DTO extends IModel<ID>, ID extends Serializable> implements ICRUDDal<DTO, ID> {

	/** long serialVersionUID */
	private static final long	serialVersionUID	= -7579819764963244505L;

	/** IDao <ID, ID_TYPE> dao */
	private IDao<DTO, ID>		dao;

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#create(com.macasa.panel.entity.api.IModel)
	 */
	@Override
	@Transactional(rollbackFor = DALException.class)
	@ILoggable
	public void create(final DTO id) throws DALException {
		try {
			this.getDao().createOrUpdate(id);
		} catch (final DAOException e) {
			Logger.error("create failed", e);
			throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#update(com.macasa.panel.entity.api.IModel)
	 */
	@Override
	@Transactional(rollbackFor = DALException.class)
	@ILoggable
	public void update(final DTO id) throws DALException {
		try {
			this.getDao().createOrUpdate(id);
		} catch (final DAOException e) {
			Logger.error("update failed", e);
			throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#delete(com.macasa.panel.entity.api.IModel)
	 */
	@Override
	@Transactional(rollbackFor = DALException.class)
	@ILoggable
	public void delete(final DTO id) throws DALException {
		if (id != null) {
			try {
				this.getDao().delete(id);
			} catch (final DAOException e) {
				Logger.error("delete failed", e);
				throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
			}
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#evict(com.macasa.panel.entity.api.IModel)
	 */
	@Override
	public void evict(final DTO id) throws DALException {
		try {
			this.getDao().evict(id);
		} catch (final DAOException e) {
			Logger.error("evict failed", e);
			throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#flush()
	 */
	@Override
	public void flush() throws DALException {
		try {
			this.getDao().flush();
		} catch (final DAOException e) {
			Logger.error("flush failed", e);
			throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#getAllId()
	 */
	@Override
	@Transactional(readOnly = true)
	@ILoggable
	public List<ID> getAllId() throws DALException {
		try {
			return this.getDao().getAllId();
		} catch (final DAOException e) {
			Logger.error("getAllId failed", e);
			throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#getAllNumber()
	 */
	@Override
	@Transactional(readOnly = true)
	@ILoggable
	public Integer getAllNumber() throws DALException {
		try {
			return this.getDao().getfindAllNumber();
		} catch (final DAOException e) {
			Logger.error("getAllNumber failed", e);
			throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#getAll()
	 */
	@Override
	@Transactional(readOnly = true)
	@ILoggable
	public List<DTO> getAll() throws DALException {
		try {
			return this.getDao().findAll();
		} catch (final DAOException e) {
			Logger.error("getAll failed", e);
			throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#getAll(int, int)
	 */
	@Override
	@Transactional(readOnly = true)
	@ILoggable
	public List<DTO> getAll(final int firstResult, final int maxResults) throws DALException {
		try {
			return this.getDao().findAll(firstResult, maxResults);
		} catch (final DAOException e) {
			Logger.error("getAll failed", e);
			throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#getFromCriteria(org.hibernate.Criteria)
	 */
	@Override
	@Transactional(readOnly = true)
	@ILoggable
	public List<DTO> getFromCriteria(final Criteria criteria) throws DALException {
		try {
			return this.getDao().findByCriteria(criteria);
		} catch (final DAOException e) {
			Logger.error("getFromCriteria failed", e);
			throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#getFromID(java.io.Serializable)
	 */
	@Override
	@Transactional(readOnly = true)
	@ILoggable
	public DTO getFromID(final ID id) throws DALException {
		try {
			return this.getDao().findById(id);
		} catch (final DAOException e) {
			Logger.error("getFromID failed", e);
			throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#getFromIDS(List)
	 */
	@Override
	@Transactional(readOnly = true)
	@ILoggable
	public List<DTO> getFromIDS(final List<ID> ids) throws DALException {
		try {
			return this.getDao().findByIds(ids);
		} catch (final DAOException e) {
			Logger.error("getFromIDS failed", e);
			throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#getFromQuery(String, Object[])
	 */
	@Override
	@Transactional(readOnly = true)
	@ILoggable
	public List<DTO> getFromQuery(final String query, final Object[] paramValues) throws DALException {
		try {
			return this.getDao().findByQuery(query, paramValues);
		} catch (final DAOException e) {
			Logger.error("getFromQuery failed", e);
			throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#getFromAttribute(String, Object)
	 */
	@Override
	@Transactional(readOnly = true)
	@ILoggable
	public List<DTO> getFromAttribute(final String attributeName, final Object value) throws DALException {
		try {
			return this.getDao().findByAttribute(attributeName, value);
		} catch (final DAOException e) {
			Logger.error("getFromAttribute failed", e);
			throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#getFromAttributes(String, List)
	 */
	@Override
	@Transactional(readOnly = true)
	@ILoggable
	public List<DTO> getFromAttributes(final String attributeName, final List<? extends Object> values) throws DALException {
		try {
			return this.getDao().findByAttributes(attributeName, values);
		} catch (final DAOException e) {
			Logger.error("getFromAttributes failed", e);
			throw new DALException(e, DALException.ERROR_CODE.DATABASE_ERROR);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#getDao()
	 */
	@Override
	public IDao<DTO, ID> getDao() {
		return this.dao;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.macasa.service.dal.api.ICRUDDal#setDao(com.macasa.panel.dao.IDao)
	 */
	@Override
	public void setDao(final IDao<DTO, ID> dao) {
		this.dao = dao;
	}

}
